package com.example.utility.crypto.rsa;

/**
 * @author 季舟
 * @Date 2024-12-18 14:25
 */

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class RSADemo {

    public static void main(String[] args) {
        try {

            verifySignature();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成RSA密钥对
     * 该方法用于生成RSA算法的公钥和私钥，并将它们打印出来
     * 使用 KeyPairGenerator 类来生成密钥对，指定算法名称为RSA，并设置密钥长度为2048位
     * 最后，将生成的公钥和私钥使用Base64编码，并打印到控制台
     *
     * @throws NoSuchAlgorithmException 如果无法获取指定算法的 KeyPairGenerator 实例
     */
    public static void generateRsaKey() throws NoSuchAlgorithmException {
        // 获取 KeyPairGenerator 实例：通过 KeyPairGenerator.getInstance("RSA") 获取一个用于生成RSA密钥对的实例。
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        // 初始化密钥生成器：调用 keyPairGenerator.initialize(2048) 设置密钥长度为2048位。
        keyPairGenerator.initialize(2048);
        // 生成密钥对：调用 keyPairGenerator.generateKeyPair() 生成一个包含公钥和私钥的 KeyPair 对象。
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        // 从 KeyPair 对象中获取公钥和私钥
        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();

        // 将公钥和私钥进行Base64编码，并将它们打印出来
        System.out.println("Public Key: " + Base64.getEncoder().encodeToString(publicKey.getEncoded()));
        System.out.println("Private Key: " + Base64.getEncoder().encodeToString(privateKey.getEncoded()));
        // Public Key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Hnwf4qVIcUsSFf5zttWouDJnoi5Kt4eOhf8Kms8sCuacnbXgbsFdPNpVb1Mu5NWgkkMD+hydeFrSLD2I/Fj7h8tfFGiYEoy7MouRvmhW7N9zQ8LRPScoCvMYdrFItVht+ghbpzasRAAiEGHdTsIUImKWrrJZpfl9pmxyoA08vbrykHuR8PWGgN0RiqIW9/3juTzUtYQZXnMa98c6Pky3fXSuXi/XVJam/RoEtzBePb8la3IsdCTbuA45LA9UM/p7YdYkahZ7Vz0elgvVNtn2npTS04DaLvkpsgoXLtEKAvB1hhTqMo2+qMhiaP0Kvpxeyners+ubDJVMe3VaKCfFwIDAQAB
        // Private Key: MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDYefB/ipUhxSxIV/nO21ai4MmeiLkq3h46F/wqazywK5pydteBuwV082lVvUy7k1aCSQwP6HJ14WtIsPYj8WPuHy18UaJgSjLsyi5G+aFbs33NDwtE9JygK8xh2sUi1WG36CFunNqxEACIQYd1OwhQiYpauslml+X2mbHKgDTy9uvKQe5Hw9YaA3RGKohb3/eO5PNS1hBlecxr3xzo+TLd9dK5eL9dUlqb9GgS3MF49vyVrcix0JNu4DjksD1Qz+nth1iRqFntXPR6WC9U22faelNLTgNou+SmyChcu0QoC8HWGFOoyjb6oyGJo/Qq+nF7Kd6uz65sMlUx7dVooJ8XAgMBAAECggEAZslPhl+4+/XxVtBfDvdapa/yS9JDibU5yP/GfiW5BTVO+navUSwKJUPGii1+F7qX4vjoP01xu8My+6r61Iozlsc7A8KHRQ02LPS7EHxLP410eD9ibHVxQSRKwVPtMuL6qSYRacIUnOoqNohW1zUWd5c3GGmEY7BQQs0rfClv+sSf8sZEJJAYF4VYNQX6kLShQlQvW/B4O75cA+iOcXI0cz6PQ5FIOPOqhpMxtlLYk7z06Rby7VcjrE8BvMKgQtPf4Jxss/LyEgn6HepSf5ObNWPJdCsWD7LhtzT1hssGPK5FmbxEkjIS/wp2QPED1YmQOzYv6ujAMH7JSFykweuFgQKBgQDz26m3VIYJ8vEoieqrLnpwAYaAr5yOlBpqcShME8C8R1pimCtu7l22E9Dr7RRJ7VBL5cLCmsub9OWsAnG42fmpIb+wn9QCsOUHzYLJ8Q0cdy/qk2THcLfGsAlywlzgoXDWIrad3O9ySE+fyNlDeV2c8lCip4dZbRXILTjgDGD44QKBgQDjQUFVJudHktBJYSUY9rY3vq9FHBfskQBqRQvcaofeYar/s8h0M482D5549abpL14GtKhnR0KxIDgiqXGY3vyI27zAxRhkbH7usyXqhBY0zjKC+oKpR4cwwMWdI4EMPg631tcN0ZduSkMkNBIsnfSk+kJUhMjKuj7f6wo+ggo+9wKBgFJsEW4EpJViRr6D9wxK1llbOqHuOUU7q74EZzFnj8JTf6pJcoy5BnWPNxM2+5+NFZHBo9Vwypb47FP6M4PeMPNIk+jX7KnILnE3thgZYGwZoNlxXiPG5mbCgz8FkKzgBCpsazrqPQhshnUkRsL2l3x/rl97rlS8eRtCpbGcnX4hAoGAHugUC5Gj6K8F1sT4d6Gt/HzZd2uvsUOzK8DCMTLn0Y205Nu9ilgsxOxw4ACAt7vybLULJiih4FcCa2xh/6lr7Oz9ibYEcDv1M19366IVJw9X/Uo2lPEeaLn+5jUa6uBRvhzg2IdFsgE1imnugtTknb9PYBFDAZc8z9U2anPjEtcCgYEAph3BBkAIdlUd17Rq7S5UB/ePEQzqBvKB8cIKgb3ypnm5trLWyn/ynDZ/3nt/EE4NTViVd1nc9fsoS2F2QRVGVQY6KNva7119E7mDsP7SG3bI4Dl6j5WSlNbKbEqfi78BuTt6p5PiEpzS9mSGr153WF9mj65AjbB7X/T0rKGj//E=

    }

    /**
     * 使用公钥加密数据。
     * <p>
     * 该方法使用RSA算法和给定的公钥对原始文本进行加密，并将加密后的数据以Base64编码的形式输出。
     * </p>
     *
     * @throws Exception 如果加密过程中发生任何异常
     */
    public static void encrypt() throws Exception {
        // 原始文本
        String originalText = "Hello, RSA encryption and decryption!";

        // 公钥的Base64编码字符串
        String publicKeyBase64 = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Hnwf4qVIcUsSFf5zttWouDJnoi5Kt4eOhf8Kms8sCuacnbXgbsFdPNpVb1Mu5NWgkkMD+hydeFrSLD2I/Fj7h8tfFGiYEoy7MouRvmhW7N9zQ8LRPScoCvMYdrFItVht+ghbpzasRAAiEGHdTsIUImKWrrJZpfl9pmxyoA08vbrykHuR8PWGgN0RiqIW9/3juTzUtYQZXnMa98c6Pky3fXSuXi/XVJam/RoEtzBePb8la3IsdCTbuA45LA9UM/p7YdYkahZ7Vz0elgvVNtn2npTS04DaLvkpsgoXLtEKAvB1hhTqMo2+qMhiaP0Kvpxeyners+ubDJVMe3VaKCfFwIDAQAB";

        // 将Base64编码的公钥转换为PublicKey对象
        PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyBase64)));

        // 创建并初始化Cipher对象用于加密
        Cipher encryptCipher = Cipher.getInstance("RSA");
        encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);

        // 对原始文本进行加密
        byte[] encryptedBytes = encryptCipher.doFinal(originalText.getBytes());

        // 输出加密后的数据，以Base64编码形式
        System.out.println("加密后的数据: " + Base64.getEncoder().encodeToString(encryptedBytes));
    }

    /**
     * 使用私钥解密数据。
     * <p>
     * 此方法使用提供的私钥对Base64编码的加密数据进行解密，并将解密后的数据输出到控制台。
     *
     * @throws Exception 如果解密过程中发生任何异常，例如私钥格式错误或解密失败。
     */
    public static void decrypt() throws Exception {
        // 解码Base64编码的加密数据
        byte[] encryptedBytes = Base64.getDecoder().decode("k1CIe+Of7bl4X/3A6fa8Gz2ONMyfuoBTN2/abQ1FhdeOcLgZTyNu5elKxTpxCguMPdUqBEcFlxzVDA1svSNm9uxn1Tqa9EfVxyKXF8X9iA2mrWl84I1ssxkl8DdIVdSz2M72SBd4J0irlSwQ5pVYoQdL+jmY9S0UPvIOd40dXM91IPxdCAFriO0JXsXJqZcA6k6jddg/c497QdW9T6e5rkZnOpU38xW/c9v59icydjz05LvBpNZv7+Lu5aNybd0ORa+HZ5YZKFk/MGKl+mZM4i+x1JyYp8TsOBkNcx70dpu5eHBNdeX6REqvCGWtcC/CApF/XFc98Tp8mfbKMsuG3A==");

        // 解码Base64编码的私钥
        String privateKeyBase64 = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDYefB/ipUhxSxIV/nO21ai4MmeiLkq3h46F/wqazywK5pydteBuwV082lVvUy7k1aCSQwP6HJ14WtIsPYj8WPuHy18UaJgSjLsyi5G+aFbs33NDwtE9JygK8xh2sUi1WG36CFunNqxEACIQYd1OwhQiYpauslml+X2mbHKgDTy9uvKQe5Hw9YaA3RGKohb3/eO5PNS1hBlecxr3xzo+TLd9dK5eL9dUlqb9GgS3MF49vyVrcix0JNu4DjksD1Qz+nth1iRqFntXPR6WC9U22faelNLTgNou+SmyChcu0QoC8HWGFOoyjb6oyGJo/Qq+nF7Kd6uz65sMlUx7dVooJ8XAgMBAAECggEAZslPhl+4+/XxVtBfDvdapa/yS9JDibU5yP/GfiW5BTVO+navUSwKJUPGii1+F7qX4vjoP01xu8My+6r61Iozlsc7A8KHRQ02LPS7EHxLP410eD9ibHVxQSRKwVPtMuL6qSYRacIUnOoqNohW1zUWd5c3GGmEY7BQQs0rfClv+sSf8sZEJJAYF4VYNQX6kLShQlQvW/B4O75cA+iOcXI0cz6PQ5FIOPOqhpMxtlLYk7z06Rby7VcjrE8BvMKgQtPf4Jxss/LyEgn6HepSf5ObNWPJdCsWD7LhtzT1hssGPK5FmbxEkjIS/wp2QPED1YmQOzYv6ujAMH7JSFykweuFgQKBgQDz26m3VIYJ8vEoieqrLnpwAYaAr5yOlBpqcShME8C8R1pimCtu7l22E9Dr7RRJ7VBL5cLCmsub9OWsAnG42fmpIb+wn9QCsOUHzYLJ8Q0cdy/qk2THcLfGsAlywlzgoXDWIrad3O9ySE+fyNlDeV2c8lCip4dZbRXILTjgDGD44QKBgQDjQUFVJudHktBJYSUY9rY3vq9FHBfskQBqRQvcaofeYar/s8h0M482D5549abpL14GtKhnR0KxIDgiqXGY3vyI27zAxRhkbH7usyXqhBY0zjKC+oKpR4cwwMWdI4EMPg631tcN0ZduSkMkNBIsnfSk+kJUhMjKuj7f6wo+ggo+9wKBgFJsEW4EpJViRr6D9wxK1llbOqHuOUU7q74EZzFnj8JTf6pJcoy5BnWPNxM2+5+NFZHBo9Vwypb47FP6M4PeMPNIk+jX7KnILnE3thgZYGwZoNlxXiPG5mbCgz8FkKzgBCpsazrqPQhshnUkRsL2l3x/rl97rlS8eRtCpbGcnX4hAoGAHugUC5Gj6K8F1sT4d6Gt/HzZd2uvsUOzK8DCMTLn0Y205Nu9ilgsxOxw4ACAt7vybLULJiih4FcCa2xh/6lr7Oz9ibYEcDv1M19366IVJw9X/Uo2lPEeaLn+5jUa6uBRvhzg2IdFsgE1imnugtTknb9PYBFDAZc8z9U2anPjEtcCgYEAph3BBkAIdlUd17Rq7S5UB/ePEQzqBvKB8cIKgb3ypnm5trLWyn/ynDZ/3nt/EE4NTViVd1nc9fsoS2F2QRVGVQY6KNva7119E7mDsP7SG3bI4Dl6j5WSlNbKbEqfi78BuTt6p5PiEpzS9mSGr153WF9mj65AjbB7X/T0rKGj//E=";

        // 生成私钥对象
        PrivateKey privateKey = KeyFactory.getInstance("RSA")
                .generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyBase64)));

        // 创建并初始化解密器
        Cipher decryptCipher = Cipher.getInstance("RSA");
        decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);

        // 执行解密操作
        byte[] decryptedBytes = decryptCipher.doFinal(encryptedBytes);

        // 将解密后的字节数组转换为字符串并输出
        String decryptedText = new String(decryptedBytes);
        System.out.println("解密后的数据: " + decryptedText);
    }

    /**
     * 使用RSA私钥对数据进行签名
     *
     * @throws Exception 如果签名过程中出现错误
     */
    private static void sign() throws Exception {
        // 要签名的数据
        String originalData = "Hello, RSA Signature!";
        // 解码Base64编码的私钥
        String privateKeyBase64 = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDYefB/ipUhxSxIV/nO21ai4MmeiLkq3h46F/wqazywK5pydteBuwV082lVvUy7k1aCSQwP6HJ14WtIsPYj8WPuHy18UaJgSjLsyi5G+aFbs33NDwtE9JygK8xh2sUi1WG36CFunNqxEACIQYd1OwhQiYpauslml+X2mbHKgDTy9uvKQe5Hw9YaA3RGKohb3/eO5PNS1hBlecxr3xzo+TLd9dK5eL9dUlqb9GgS3MF49vyVrcix0JNu4DjksD1Qz+nth1iRqFntXPR6WC9U22faelNLTgNou+SmyChcu0QoC8HWGFOoyjb6oyGJo/Qq+nF7Kd6uz65sMlUx7dVooJ8XAgMBAAECggEAZslPhl+4+/XxVtBfDvdapa/yS9JDibU5yP/GfiW5BTVO+navUSwKJUPGii1+F7qX4vjoP01xu8My+6r61Iozlsc7A8KHRQ02LPS7EHxLP410eD9ibHVxQSRKwVPtMuL6qSYRacIUnOoqNohW1zUWd5c3GGmEY7BQQs0rfClv+sSf8sZEJJAYF4VYNQX6kLShQlQvW/B4O75cA+iOcXI0cz6PQ5FIOPOqhpMxtlLYk7z06Rby7VcjrE8BvMKgQtPf4Jxss/LyEgn6HepSf5ObNWPJdCsWD7LhtzT1hssGPK5FmbxEkjIS/wp2QPED1YmQOzYv6ujAMH7JSFykweuFgQKBgQDz26m3VIYJ8vEoieqrLnpwAYaAr5yOlBpqcShME8C8R1pimCtu7l22E9Dr7RRJ7VBL5cLCmsub9OWsAnG42fmpIb+wn9QCsOUHzYLJ8Q0cdy/qk2THcLfGsAlywlzgoXDWIrad3O9ySE+fyNlDeV2c8lCip4dZbRXILTjgDGD44QKBgQDjQUFVJudHktBJYSUY9rY3vq9FHBfskQBqRQvcaofeYar/s8h0M482D5549abpL14GtKhnR0KxIDgiqXGY3vyI27zAxRhkbH7usyXqhBY0zjKC+oKpR4cwwMWdI4EMPg631tcN0ZduSkMkNBIsnfSk+kJUhMjKuj7f6wo+ggo+9wKBgFJsEW4EpJViRr6D9wxK1llbOqHuOUU7q74EZzFnj8JTf6pJcoy5BnWPNxM2+5+NFZHBo9Vwypb47FP6M4PeMPNIk+jX7KnILnE3thgZYGwZoNlxXiPG5mbCgz8FkKzgBCpsazrqPQhshnUkRsL2l3x/rl97rlS8eRtCpbGcnX4hAoGAHugUC5Gj6K8F1sT4d6Gt/HzZd2uvsUOzK8DCMTLn0Y205Nu9ilgsxOxw4ACAt7vybLULJiih4FcCa2xh/6lr7Oz9ibYEcDv1M19366IVJw9X/Uo2lPEeaLn+5jUa6uBRvhzg2IdFsgE1imnugtTknb9PYBFDAZc8z9U2anPjEtcCgYEAph3BBkAIdlUd17Rq7S5UB/ePEQzqBvKB8cIKgb3ypnm5trLWyn/ynDZ/3nt/EE4NTViVd1nc9fsoS2F2QRVGVQY6KNva7119E7mDsP7SG3bI4Dl6j5WSlNbKbEqfi78BuTt6p5PiEpzS9mSGr153WF9mj65AjbB7X/T0rKGj//E=";

        // 生成私钥对象
        PrivateKey privateKey = KeyFactory.getInstance("RSA")
                .generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyBase64)));

        // 创建Signature对象并初始化为签名操作
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        // 更新签名内容
        signature.update(originalData.getBytes());
        // 执行签名并获取签名结果
        byte[] signatureBase64 = signature.sign();
        // 打印签名结果
        System.out.println("签名: " + Base64.getEncoder().encodeToString(signatureBase64));
    }

    /**
     * 验证RSA签名的私有静态方法
     *
     * @throws Exception 如果签名验证过程中发生错误
     */
    private static void verifySignature() throws Exception {
        // 要签名的数据
        String originalData = "Hello, RSA Signature!";
        // 公钥的Base64编码字符串
        String publicKeyBase64 = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Hnwf4qVIcUsSFf5zttWouDJnoi5Kt4eOhf8Kms8sCuacnbXgbsFdPNpVb1Mu5NWgkkMD+hydeFrSLD2I/Fj7h8tfFGiYEoy7MouRvmhW7N9zQ8LRPScoCvMYdrFItVht+ghbpzasRAAiEGHdTsIUImKWrrJZpfl9pmxyoA08vbrykHuR8PWGgN0RiqIW9/3juTzUtYQZXnMa98c6Pky3fXSuXi/XVJam/RoEtzBePb8la3IsdCTbuA45LA9UM/p7YdYkahZ7Vz0elgvVNtn2npTS04DaLvkpsgoXLtEKAvB1hhTqMo2+qMhiaP0Kvpxeyners+ubDJVMe3VaKCfFwIDAQAB";

        // 将Base64编码的公钥转换为PublicKey对象
        PublicKey publicKey = KeyFactory.getInstance("RSA")
                .generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyBase64)));

        // 解码签名
        byte[] signature = Base64.getDecoder().decode("IIafXexTMPfHSljBEchJqODHOrfJPfw8k0Yh7g3iXS7IcL6DrLJlb0RITztIMQ4Wim0ERV/fS8nmRYvY34dWQ2LMJq/IoCCNxLdW1Vpr+Q+x0U7cuRJbqvwokBHgbS94zTCJXLe+xruZnEMgG+plLhJ6LsXKibwxULJbq0AMnWNrpRWB3DYyZdhJRsbGEpv1kJxQApBJ1SRbQHuZHrWMgOAcHNSniW6WmE67sWixcLZvCnzuplfkb8Qe4JPpD+jrx1m04sA+tgeg92KCkTn2m/Hv4IS3Gc6WNnbRk9V7/t+SSO7ThnSPZOBpyV3qrH6omfs67nXg3DCBZC7+uSH1CA==");

        // 初始化签名对象，指定签名算法
        Signature sig = Signature.getInstance("SHA256withRSA");
        // 使用公钥初始化验证操作
        sig.initVerify(publicKey);
        // 更新签名对象的数据
        sig.update(originalData.getBytes());
        // 执行签名验证
        boolean isVerified = sig.verify(signature);
        // 打印签名验证结果
        System.out.println("签名验证结果: " + (isVerified ? "成功" : "失败"));
    }
}

